package drds.configuration.web.task;

import drds.configuration.common.Constants;
import drds.configuration.db.table_mapping.TableInfo;
import lombok.extern.slf4j.Slf4j;

import java.math.BigInteger;
import java.sql.Connection;
import java.util.*;
//列信息记录

//                    TABLE_CATALOG	varchar	512	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    TABLE_SCHEMA	varchar	64	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    TABLE_NAME	varchar	64	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    COLUMN_NAME	varchar	64	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0


//                    ORDINAL_POSITION	bigint	21	0	0	0	-1	0	0	0	0					0	0
//                    COLUMN_DEFAULT	longtext	0	0	-1	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    IS_NULLABLE	varchar	3	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    DATA_TYPE	varchar	64	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    CHARACTER_MAXIMUM_LENGTH	bigint	21	0	-1	0	-1	0	0		0					0	0
//                    CHARACTER_OCTET_LENGTH	bigint	21	0	-1	0	-1	0	0		0					0	0
//                    NUMERIC_PRECISION	bigint	21	0	-1	0	-1	0	0		0					0	0
//                    NUMERIC_SCALE	bigint	21	0	-1	0	-1	0	0		0					0	0
//                    DATETIME_PRECISION	bigint	21	0	-1	0	-1	0	0		0					0	0
//                    CHARACTER_SET_NAME	varchar	32	0	-1	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    COLLATION_NAME	varchar	32	0	-1	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    COLUMN_TYPE	longtext	0	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    COLUMN_KEY	varchar	3	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    EXTRA	varchar	30	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    PRIVILEGES	varchar	80	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    COLUMN_COMMENT	varchar	1024	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    IS_GENERATED	varchar	6	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
//                    GENERATION_EXPRESSION	longtext	0	0	-1	0	0	0	0		0		utf8	utf8_general_ci		0	0

/**
 * 该只是对比基础表信息,顺序和字段信息-类型-长度-默认值-是否主键.
 * 在设计表结构的时候,分为三种增加修改删除,即A比B表多字段，少字段，存在相同的字段则比较每个字段的差异，一点都不能出错。
 */
@Slf4j
public class CheckTableBaseColumn {
    //show databases;
    //show tables from drds_home
    public static final String column_name = "column_name";

    public static void check(List<TableInfo> tableInfoList, Properties properties) throws Exception {
        List<String> tableNameList = new ArrayList<String>();
        for (TableInfo tableInfo :
                tableInfoList) {
            if (tableInfo.isCheckBaseColumn()) {
                tableNameList.add(tableInfo.getTableName());
                System.out.println("需要对比的表" + tableInfo.getTableName());
            }
        }
        //
        Connection connection = JdbcUtil.getConnection(properties);
        Map<String, Map<String, Object>> mapMapOfModelTable = new HashMap<String, Map<String, Object>>();
        List<Map<String, Object>> mapListOfModelTable = null;
        try {
            mapListOfModelTable = JdbcUtil.get(connection, "select t.* from INFORMATION_SCHEMA.Columns  t where t.table_name='model_table'", null);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.close(null, null, connection);
        }
        /**
         * 依次按照列名进行处理
         */
        List<String> columnNameListOfModelTable = new ArrayList<String>();
        if (Constants.devMode) {
            System.out.println("模版表:model_table");
        }
        for (Map<String, Object> map : mapListOfModelTable) {
            for (String key : map.keySet()) {
                if (Constants.devMode) {
                    System.out.println("column_name:" + key + "," + map.get(key));
                }
            }
            String columnName = (String) map.get(column_name);
            columnNameListOfModelTable.add(columnName);
            mapMapOfModelTable.put(columnName, map);
        }
        for (String tableName : tableNameList) {
            checkTableColumn(mapMapOfModelTable, columnNameListOfModelTable, tableName, properties);
        }


    }

    /**
     * @param mapMapOfModelTable         基础模版
     * @param columnNameListOfModelTable 基础模版列
     * @param tableName                  需要对照的表名
     */
    public static void checkTableColumn(Map<String, Map<String, Object>> mapMapOfModelTable, List<String> columnNameListOfModelTable, String tableName, Properties properties) throws Exception {
        Connection connection = JdbcUtil.getConnection(properties);
        List<Object> objectList = new ArrayList<Object>();
        objectList.add(tableName);
        //
        List<Map<String, Object>> mapList = JdbcUtil.get(connection, "select t.* from INFORMATION_SCHEMA.Columns  t where t.table_name=?", objectList);
        if (Constants.devMode) {
            log.info("验证基础字段的顺序");
        }
        int index = 0;
        for (Map<String, Object> map : mapList) {
            String columnName = (String) map.get(column_name);
            String columnNameBaseOnIndex = columnNameListOfModelTable.get(index);
            if (!columnName.equals(columnNameBaseOnIndex)) {
                String msg = "在" + tableName + "表中,列不匹配,index:" + index + ",columnNameBaseOnIndex=" + columnNameBaseOnIndex + "," + columnName + "=" + columnName;
                throw new RuntimeException(msg);
            }
            index++;
            if (index == columnNameListOfModelTable.size()) {
                break;
            }
        }
        //
        if (Constants.devMode) {
            log.info("验证基础字段的列信息是否相同");
        }
        for (Map<String, Object> map : mapList) {
            //判断是否在模版列中,如果不存在则结束
            String columnName = (String) map.get(column_name);
            if (!mapMapOfModelTable.containsKey(columnName)) {
                break;
            }
            if (Constants.devMode) {
                log.info("columnName:" + columnName);
            }
            //主键校验
            //先按照类型进行校验
            //再校验默认值
            //长度检验
            Map<String, Object> mapOfModelTable = mapMapOfModelTable.get(columnName);
            //map mapOfModelTable
            for (String keyOfModelTable : mapOfModelTable.keySet()) {
                //首先检查是否在对方
                if (!map.containsKey(keyOfModelTable)) {
                    String msg = " 在" + tableName + "表中,字段:" + keyOfModelTable + "不存在";
                    throw new RuntimeException(msg);
                }
                Object objectOfModelTable = mapOfModelTable.get(keyOfModelTable);
                Object object = map.get(keyOfModelTable);
                if (objectOfModelTable == null && object == null) {
                    //
                } else if ((objectOfModelTable == null && object != null) || (objectOfModelTable != null && object == null)) {
                    //直接存在不一致
                    String msg = " 在" + tableName + "表中,字段:" + keyOfModelTable + "ordinal_position不一致,模版表是:" + objectOfModelTable + ",当前表是:" + object;
                    log.error(msg);
                    throw new RuntimeException(msg);
                } else if (object != null && objectOfModelTable != null) {
                    {
                        String msg = " 在" + tableName + "中," + keyOfModelTable + "字段值,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                        log.info(msg);
                    }

                    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    //                    table_catalog	varchar	512	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
                    //                    table_schema	varchar	64	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
                    //                    table_name	varchar	64	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0
                    //                    column_name	varchar	64	0	0	0	0	0	0		0		utf8	utf8_general_ci		0	0

                    //具体列信息
                    //                    ordinal_position	bigint        第几列
                    //                    column_default	longtext      默认值
                    //                    is_nullable	varchar           是否为空
                    //                    data_type	varchar               数据类型
                    //                    character_maximum_length	bigint字符最大长度
                    //                    character_octet_length	bigint
                    //                    numeric_precision	bigint        数字精度
                    //                    numeric_scale	bigint            数字小数位
                    //                    datetime_precision	bigint    日期精度
                    //                    character_set_name	varchar   字符名字
                    //                    collation_name	varchar       collation
                    //                    column_type	longtext          列类型
                    //                    column_key	varchar           列key
                    //                    extra	varchar	30                extra
                    //                    privileges	varchar           权限
                    //                    column_comment	varchar       列注释
                    //                    is_generated	varchar           是否自增
                    //                    generation_expression	longtext


//                    ordinal_position 	bigint
                    if ("ordinal_position".equals(keyOfModelTable)) {
                        BigInteger ordinal_position = (BigInteger) object;
                        BigInteger ordinal_positionOfModelTable = (BigInteger) objectOfModelTable;
                        if (ordinal_position.compareTo(ordinal_positionOfModelTable) != 0) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
//                    column_default	longtext
                    if ("column_default".equals(keyOfModelTable)) {
                        String column_default = (String) object;
                        String column_defaultIn$model_table = (String) objectOfModelTable;
                        if (!column_default.equals(column_defaultIn$model_table)) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
//                    is_nullable	varchar
                    if ("is_nullable".equals(keyOfModelTable)) {
                        String is_nullable = (String) object;
                        String is_nullableIn$model_table = (String) objectOfModelTable;
                        if (!is_nullable.equals(is_nullableIn$model_table)) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
//                    data_type	varchar
                    if ("data_type".equals(keyOfModelTable)) {
                        String data_type = (String) object;
                        String data_typeIn$model_table = (String) objectOfModelTable;
                        if (!data_type.equals(data_typeIn$model_table)) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
//                    character_maximum_length	bigint
                    if ("character_maximum_length".equals(keyOfModelTable)) {
                        BigInteger character_maximum_length = (BigInteger) object;
                        BigInteger character_maximum_lengthIn$model_table = (BigInteger) objectOfModelTable;
                        if (character_maximum_length.compareTo(character_maximum_lengthIn$model_table) != 0) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
                    //CHARACTER_OCTET_LENGTH应与CHARACTER_MAXIMUM_LENGTH相同，但多字节字符集除外。
//                    character_octet_length	bigint
                    if ("character_octet_length".equals(keyOfModelTable)) {
                        //not check  character_maximum_length: character_octet_length=1:4
                    }
//                    numeric_precision	bigint
                    if ("numeric_precision".equals(keyOfModelTable)) {//num-1
                        BigInteger numeric_precision = (BigInteger) object;
                        BigInteger numeric_precisionIn$model_table = (BigInteger) objectOfModelTable;
                        if (numeric_precision.compareTo(numeric_precisionIn$model_table) != 0) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);

                        }
                    }
//                    numeric_scale	bigint
                    if ("numeric_scale".equals(keyOfModelTable)) {
                        BigInteger numeric_scale = (BigInteger) object;
                        BigInteger numeric_scaleIn$model_table = (BigInteger) objectOfModelTable;
                        if (numeric_scale.compareTo(numeric_scaleIn$model_table) != 0) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
//                    datetime_precision	bigint
                    if ("datetime_precision".equals(keyOfModelTable)) {
                        BigInteger datetime_precision = (BigInteger) object;
                        BigInteger datetime_precisionIn$model_table = (BigInteger) objectOfModelTable;
                        if (datetime_precision.compareTo(datetime_precisionIn$model_table) != 0) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
                    //字符编码都是一个东西,统一
//                    character_set_name	varchar
                    if ("character_set_name".equals(keyOfModelTable)) {
                        //not check
                    }
//                    collation_name	varchar
                    if ("collation_name".equals(keyOfModelTable)) {
                        //not check
                    }
//                    column_type	longtext
                    if ("column_type".equals(keyOfModelTable)) {
                        String column_type = (String) object;
                        String column_typeIn$model_table = (String) objectOfModelTable;
                        if (!column_type.equals(column_typeIn$model_table)) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
//                    column_key	varchar
                    if ("column_key".equals(keyOfModelTable)) {//PRI
                        String column_key = (String) object;
                        String column_keyIn$model_table = (String) objectOfModelTable;
                        if (!column_key.equals(column_keyIn$model_table)) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
//                    extra	varchar	30
                    if ("extra".equals(keyOfModelTable)) {//auto_increment or on update current_timestamp()
                        String extra = (String) object;
                        String extraIn$model_table = (String) objectOfModelTable;
                        if (!extra.equals(extraIn$model_table)) {
                            String errorInfo = " 在" + tableName + "中," + keyOfModelTable + "字段值不一致,模版表值是:" + objectOfModelTable + ",当前表值是:" + object;
                            throw new RuntimeException(errorInfo);
                        }
                    }
//                    privileges	varchar
                    if ("privileges".equals(keyOfModelTable)) {
                        //not check
                    }
//                    column_comment	varchar
                    if ("column_comment".equals(keyOfModelTable)) {
                        //not check
                    }
//                    is_generated	varchar
                    if ("is_generated".equals(keyOfModelTable)) {
                        //not check
                    }
//                    generation_expression	longtext
                    if ("generation_expression".equals(keyOfModelTable)) {
                        //not check
                    }


                }

            }


        }
        System.out.println("校验成功");
    }

}